package com.xq.shop.service.impl;

//import static org.bytedeco.opencv.global.opencv_imgcodecs.*;
//import org.bytedeco.opencv.opencv_core.*;
import com.alibaba.druid.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xq.shop.config.FileConfig;
import com.xq.shop.dao.domain.entity.MyFile;
import com.xq.shop.dao.mapper.FileMapper;
import com.xq.shop.service.IFileService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xq.shop.utils.ImageUtil;
import com.xq.shop.utils.MyConstants;
import com.xq.shop.vo.FileVo;
import enums.DataStatus;
import enums.ResultCodes;
import exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.velocity.shaded.commons.io.FilenameUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import utils.BaseConstants;
import utils.PasswordUtil;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

/**
 * <p>
 * 文件表 服务实现类
 * </p>
 *
 * @author gaoxiaojin
 * @since 2024-07-16
 */
@Service
@Slf4j
public class FileServiceImpl extends ServiceImpl<FileMapper, MyFile> implements IFileService {

    @Value("${xq.file.path}")
    private String filePath;

    @Resource
    private FileConfig fileConfig;

    @Override
    public FileVo upload(MultipartFile file) {

        //获取文件原始名
        String originalFilename = file.getOriginalFilename();
        assert originalFilename != null;
        String[] types = originalFilename.split("\\.");
        String fileType = types[types.length - 1].toLowerCase();
        if (StringUtils.isEmpty(fileType)) {
            throw new BusinessException(ResultCodes.ILLEGAL_FILE);
        }
        String uuidFilename = UUID.randomUUID().toString().replaceAll("-", "");
        String filename = uuidFilename + "." + fileType;
        Calendar calendar = Calendar.getInstance();
        String url = calendar.get(Calendar.YEAR) + "/" +
                (calendar.get(Calendar.MONTH) + 1) + "/" +
                calendar.get(Calendar.DATE) + "/" +
                filename;
        String realPath = filePath + url;
        File uploadFile = new File(realPath);
        if(!uploadFile.exists()){
            boolean s = uploadFile.mkdirs();
            if (!s) {
                throw new BusinessException(ResultCodes.CREATE_DIRECTORY);
            }
        }

        try {
            file.transferTo(uploadFile);
            ImageUtil.compression(realPath,fileType);
            //compressImage(realPath);
        } catch (Exception e) {
            log.error("文件上传失败：{}", e.getMessage());
            throw new BusinessException(ResultCodes.UPLOAD_ERROR);
        }

        //上传的文件保存到数据库里面
        FileVo vo = new FileVo();
        MyFile lockFile = new MyFile();
        lockFile.setFileType(fileType);
        lockFile.setSize(file.getSize());
        lockFile.setFilename(filename);
        lockFile.setOriginalFilename(originalFilename);
        lockFile.setUrl(BaseConstants.URL_PREFIX + url);
        save(lockFile);
        BeanUtils.copyProperties(lockFile, vo);
        vo.setUrl(fileConfig.montageUrl(vo.getUrl()));
        return vo;
    }

    @Override
    public FileVo uploadFile(MultipartFile file) {

        //获取文件原始名
        String originalFilename = file.getOriginalFilename();
        assert originalFilename != null;
        String[] types = originalFilename.split("\\.");
        String fileType = types[types.length - 1].toLowerCase();
        if (StringUtils.isEmpty(fileType)) {
            throw new BusinessException(ResultCodes.ILLEGAL_FILE);
        }
        String uuidFilename = UUID.randomUUID().toString().replaceAll("-", "");
        String filename = uuidFilename + "." + fileType;
        Calendar calendar = Calendar.getInstance();
        String url = calendar.get(Calendar.YEAR) + "/" +
                (calendar.get(Calendar.MONTH) + 1) + "/" +
                calendar.get(Calendar.DATE) + "/" +
                filename;
        String realPath = filePath + url;
        File uploadFile = new File(realPath);
        if(!uploadFile.exists()){
            boolean s = uploadFile.mkdirs();
            if (!s) {
                throw new BusinessException(ResultCodes.CREATE_DIRECTORY);
            }
        }

        try {
            file.transferTo(uploadFile);
            //compressImage(realPath);
        } catch (Exception e) {
            log.error("文件上传失败：{}", e.getMessage());
            throw new BusinessException(ResultCodes.UPLOAD_ERROR);
        }

        //上传的文件保存到数据库里面
        FileVo vo = new FileVo();
        MyFile lockFile = new MyFile();
        lockFile.setFileType(fileType);
        lockFile.setSize(file.getSize());
        lockFile.setFilename(filename);
        lockFile.setOriginalFilename(originalFilename);
        lockFile.setUrl(BaseConstants.URL_PREFIX + url);
        save(lockFile);
        BeanUtils.copyProperties(lockFile, vo);
        vo.setUrl(fileConfig.montageUrl(vo.getUrl()));
        return vo;
    }

    public static void main(String[] args) {
        String p = "123456";
        System.out.println(PasswordUtil.enPawKey(p, MyConstants.KEY1, MyConstants.KEY2, MyConstants.KEY3));
    }


    @Override
    public Integer upload(byte[] fileContent, String filename) throws IOException {
        String fileType = FilenameUtils.getExtension(filename);
        if (fileType.isEmpty()) {
            log.error("文件下载失败");
        }
        Calendar calendar = Calendar.getInstance();
        String url = calendar.get(Calendar.YEAR) + "/" +
                (calendar.get(Calendar.MONTH) + 1) + "/" +
                calendar.get(Calendar.DATE) + "/" +
                filename;

        String realPath = this.filePath + url;
        Path path = Paths.get(realPath);

        // 确保父目录存在
        if (!Files.exists(path.getParent())) {
            Files.createDirectories(path.getParent());
        }

        // 写入文件
        Files.write(path, fileContent);
        //compressImage(realPath);
        ImageUtil.compression(realPath,fileType);
        // 创建并保存文件信息到数据库
        MyFile myFile = new MyFile();
        myFile.setFileType(fileType);
        myFile.setSize((long) fileContent.length);
        myFile.setFilename(filename);
        myFile.setOriginalFilename(filename);
        myFile.setUrl(BaseConstants.URL_PREFIX + url);
        save(myFile);
        return myFile.getId();
    }

//    private static void compressImage(String url) {
//        int jpegQuality = 70;
//        // 读取图片
//        Mat image = imread(url);
//        if (image.empty()) {
//            System.err.println("Cannot read image: " + url);
//            return;
//        }
//        // 设置JPEG压缩参数
//        int[] compressionParams = {IMWRITE_JPEG_QUALITY, jpegQuality};
//        // 保存压缩后的图片
//        imwrite(url, image, compressionParams);
//        System.out.println("压缩成功");
//    }

    @Override
    public Map<Integer, String> selectFileUrl(List<Integer> ids) {
        LambdaQueryWrapper<MyFile> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(MyFile::getStatus, DataStatus.NORMAL.getCode());
        wrapper.in(MyFile::getId, ids);
        List<MyFile> imageList = list(wrapper);
        Map<Integer, String> imageMap = new HashMap<>();
        imageList.forEach(image -> imageMap.put(image.getId(), fileConfig.montageUrl(image.getUrl())));
        return imageMap;
    }

    @Override
    public void deleteFile(Integer id) {
        MyFile file = getById(id);
        if (Objects.nonNull(file)) {
            // 删除服务器文件
            String path = filePath + file.getUrl().replaceAll("/qfile/", "");
            // 创建File对象
            File f = new File(path);
            // 创建File对象
            // 判断文件是否存在
            if (f.exists()) {
                // 尝试删除文件
                if (f.delete()) {
                    file.setStatus(DataStatus.INVALID.getCode());
                    updateById(file);
                    log.info("File deleted successfully: " + path);
                } else {
                    log.error("Failed to delete the file: " + path);
                }
            } else {
                log.warn("File not found: " + path);
            }
        }
    }
}
